package com.sx.pipeline.ui.map

import android.Manifest
import android.graphics.Color
import android.os.Bundle
import android.text.TextUtils
import android.view.MotionEvent
import android.view.View
import android.widget.CompoundButton
import android.widget.EditText
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.maps.*
import com.amap.api.maps.model.*
import com.amap.api.services.core.AMapException
import com.amap.api.services.district.DistrictItem
import com.amap.api.services.district.DistrictSearch
import com.amap.api.services.district.DistrictSearchQuery
import com.blankj.utilcode.util.KeyboardUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ToastUtils
import com.google.gson.Gson
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.permissionx.guolindev.PermissionX
import com.sx.mvvmlibs.binding.edittext.viewAdapter
import com.sx.mvvmlibs.utils.Logs
import com.sx.pipeline.BR
import com.sx.pipeline.R
import com.sx.pipeline.app.base.CYDataBindingBaseFragment
import com.sx.pipeline.app.config.IdentityType
import com.sx.pipeline.arouth.RouteManager
import com.sx.pipeline.databinding.FragMap2Binding
import com.sx.pipeline.repos.http.req.DistrictBorderDTO
import com.sx.pipeline.repos.local.db.table.FileNodesBeanDO
import com.sx.pipeline.repos.local.db.table.PipeFileBeanDO
import com.sx.pipeline.ui.map.entity.DrawLatLng
import com.sx.pipeline.ui.map.tools.DrawMapUtils

/**
 * @Author: YY
 * @Date: 2022/8/9
 * @Desc: TODO
 */
class Map2Fragment : CYDataBindingBaseFragment<FragMap2Binding, MapVM>(R.layout.frag_map2),
    View.OnClickListener, CompoundButton.OnCheckedChangeListener, LocationSource,
    AMap.OnMapClickListener, AMap.OnMarkerClickListener, AMap.OnMapTouchListener,
    AMapLocationListener {

    private lateinit var aMap: AMap
    private lateinit var mPopup: BasePopupView

    private val polygonList: MutableList<Polygon> = mutableListOf()

    // 绘制点列表
    private val pointList: MutableList<DrawLatLng> = mutableListOf()

    // 编辑状态
    private var isEditor: Boolean = false

    // 定位
    private var mLocationListener: LocationSource.OnLocationChangedListener? = null
    private var mLocationClient: AMapLocationClient? = null
    private var mLocationOption: AMapLocationClientOption? = null

    override fun initIdentity(type: Int) {
        super.initIdentity(type)
        Logs.d("initIdentity $type")
        when (type) {
            IdentityType.SUPPLIER.code -> {
                mBinding.tgTerritory.textOn = "服务区域"
                mBinding.tgTerritory.textOff = "服务区域"
                mBinding.tvPipeline.visibility = View.GONE
                mBinding.viewPipeline.visibility = View.GONE
            }
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        mBinding.mapView.onSaveInstanceState(outState)
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mBinding.mapView.onCreate(savedInstanceState)
        if (!this::aMap.isInitialized) {
            aMap = mBinding.mapView.map
        }
        // 初始化定位
        initMapLocation()
    }

    override fun onResume() {
        super.onResume()
        mBinding.mapView.onResume()
    }

    override fun onPause() {
        super.onPause()
        mBinding.mapView.onPause()
    }

    override fun onDestroyView() {
        mBinding.mapView.onDestroy()
        DistrictDrawHelper.clearDraw()
        super.onDestroyView()
    }

    override fun initData() {
        mBinding.setVariable(BR.onClick, this)
        mBinding.setVariable(BR.onCheckedChanged, this)

    }

    override fun initViewObservable() {
        super.initViewObservable()

        // 绘制成功
        observe(mViewModel.drawTerritoryEvent) {
            isEditor = false
            mBinding.tgEdit.isChecked = false
            mBinding.line1.visibility = View.GONE
            DistrictDrawHelper.clearDraw()
        }

        // 显示负责区域
        showTerritory()

        observe(mViewModel.territoryListEven2t) {
            ThreadUtils.getIoPool().execute {
                removeMypolyline()
                it?.let { it1 -> getMapObj(it1) }
            }

        }

        observe(mViewModel.districtBorderListEvent) {
            ThreadUtils.getIoPool().execute {
                removeDistrictMap()
                it?.forEachIndexed { index, districtBorderDTO ->
                    searchDistrict(index,districtBorderDTO.name)
                }
            }
        }
    }


    override fun onClick(v: View?) {
        when (v!!.id) {
            R.id.ll_last_step -> {
                // 上一步
                DistrictDrawHelper.lastStep()
            }
            R.id.ll_submit -> {
                // 保存
                if (DistrictDrawHelper.getHasDrawFinish()) {
                    showInputDialog()
                } else {
                    ToastUtils.showShort("请闭合绘制图形")
                }
            }
            R.id.image_cut -> {
                // 底图切换
                showSelectMapDialog()
            }
            R.id.tv_district -> {
                // 负责区域
                RouteManager.Territory.intentToTerritoryPage(3)
            }
            R.id.tv_pipeline -> {
                // 我的管线
                RouteManager.LinePipe.intentToLinePipePage()
            }
            R.id.tv_add_location -> {
                // 行政区域
                RouteManager.Main.intentToDistrictBorder()
            }
        }
    }

    override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
        when (buttonView!!.id) {
            R.id.tg_edit -> {
                isEditor = isChecked
                if (isChecked) {
                    mBinding.tgEdit.textOn = "取消编辑"
                    mBinding.line1.visibility = View.VISIBLE
                } else {
                    DistrictDrawHelper.clearDraw()
                    mBinding.line1.visibility = View.GONE
                }
            }
            R.id.tg_territory -> {
                if (isChecked) mViewModel.getTerritoryList() else removeAllPolygon()
            }
            R.id.tv_pipeline -> {
                if (isChecked) mViewModel.getLocalMapList() else removeMypolyline()
            }
            R.id.tv_district -> {
                if (isChecked) mViewModel.getDistrictBorderList() else removeDistrictMap()
            }
        }
    }

    override fun activate(onLocationListener: LocationSource.OnLocationChangedListener?) {
        this.mLocationListener = onLocationListener
        Logs.d("activate")
        if (mLocationClient == null) {
            mLocationClient = AMapLocationClient(requireContext())
            mLocationClient!!.setLocationListener(this)

            mLocationOption = AMapLocationClientOption()
            //只定位一次
            mLocationOption!!.isOnceLocation = true
            mLocationOption!!.locationMode =
                AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
            mLocationClient!!.setLocationOption(mLocationOption)
            mLocationClient!!.startLocation()
        }
    }

    override fun deactivate() {
        mLocationListener = null
        if (mLocationClient != null) {
            mLocationClient!!.stopLocation()
            mLocationClient!!.onDestroy()
        }
        mLocationClient = null
        mLocationOption = null
    }

    override fun onLocationChanged(location: AMapLocation?) {
        if (location != null && this.mLocationListener != null) {
            if (location.errorCode == 0) {
                mLocationListener!!.onLocationChanged(location)
                val mLatitude: Double = location.latitude
                val mLongitude: Double = location.longitude
            } else {
            }
        }
    }


    override fun onMapClick(latLng: LatLng?) {
        if (isEditor) {
            if (!this::aMap.isInitialized) {
                return
            }
            DistrictDrawHelper.drawPoints(requireContext(), latLng!!, aMap)
        }
    }

    override fun onMarkerClick(marker: Marker?): Boolean {
        DistrictDrawHelper.drawDistrict(marker!!)
        return true
    }

    override fun onTouch(ev: MotionEvent?) {
        DistrictDrawHelper.handleTouchEvent(ev!!)
    }

    /**
     * 初始化地图定位
     */
    private fun initMapLocation() {
        val myLocationStyle = MyLocationStyle()
        myLocationStyle.strokeColor(Color.BLACK)
        myLocationStyle.radiusFillColor(Color.argb(100, 0, 0, 180))
        myLocationStyle.strokeWidth(1.0f)
        // myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE)
        // 设置连续定位模式下的定位间隔
        // myLocationStyle.interval(10000)
        // 地图定位
        aMap.setLocationSource(this)
        // 缩放比例
        aMap.moveCamera(CameraUpdateFactory.zoomTo(16f))
        // 设置定位蓝点的Style
        aMap.myLocationStyle = myLocationStyle
        // 设置默认定位按钮是否显示
        aMap.uiSettings.isMyLocationButtonEnabled = true
        // 设置缩放按钮是否显示
        aMap.uiSettings.isZoomControlsEnabled = false
        // 设置比例尺控件是否显示
        aMap.uiSettings.isScaleControlsEnabled = true
        // 关闭旋转手势
        aMap.uiSettings.isRotateGesturesEnabled = false
        // 关闭倾斜手势
        aMap.uiSettings.isTiltGesturesEnabled = false
        // 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位
        aMap.isMyLocationEnabled = true
        // 设置地图点击事件
        aMap.setOnMapClickListener(this)
        // 设置Marker标记点击事件
        aMap.setOnMarkerClickListener(this)
        // 地图图层触摸事件
        aMap.setOnMapTouchListener(this)
    }

    /**
     * 输入名称
     */
    private fun showInputDialog() {
        mPopup = XPopup.Builder(requireContext())
            .autoDismiss(false)
            .asInputConfirm("请输入名称",
                "", "绘制名称") {
                if (!TextUtils.isEmpty(it)) {
                    mViewModel.addTerritory(it, DistrictDrawHelper.getPointList())
                    mPopup.dismiss()
                } else {
                    ToastUtils.showShort("请输入名称")
                }
            }.also {
                val editText = it.findViewById<EditText>(com.lxj.xpopup.R.id.et_input)
                viewAdapter.filterEditText(editText, true)
            }.show()
    }

    /**
     * 显示负责区域
     */
    private fun showTerritory() {
        observe(mViewModel.territoryListEvent) {
            ThreadUtils.getIoPool().execute {
                var drawLatLng: DrawLatLng
                if (it != null && it.records.isNotEmpty()) {
                    it.records.forEach { territoryVO ->
                        pointList.clear()
                        territoryVO.centerList.forEach { centerList ->
                            val latLng =
                                LatLng(centerList.latitude.toDouble(), centerList.longitude.toDouble())
                            drawLatLng = DrawLatLng(latLng, false)
                            if (territoryVO?.type != 0) {
                                drawLatLng = DrawLatLng(convert(latLng)!!, false)
                            }
                            pointList.add(drawLatLng)
                        }
                        drawPolygon()
                    }
                }
            }

        }
    }

    /**
     * 绘制多边形
     */
    private fun drawPolygon() {
        if (pointList.size <= 2) {
            return
        }
        // 多边形参数对象
        val polygonOptions = PolygonOptions()
        // 添加 多边形的每个顶点（顺序添加）
        for (i in pointList.indices) {
            polygonOptions.add(pointList[i].latLng)
        }
        polygonOptions.strokeWidth(2f)
            .strokeColor(Color.parseColor("#ffffff")) // 边框颜色
            .fillColor(Color.parseColor("#66000000")) // 多边形的填充色
        val polygon = this.aMap.addPolygon(polygonOptions.zIndex(100f))
        polygonList.add(polygon)
    }

    /**
     * 移除全部矩形
     */
    private fun removeAllPolygon() {
        polygonList.forEach {
            it.remove()
        }
    }

    /**
     * 底图切换
     */
    private fun showSelectMapDialog() {
        XPopup.Builder(activity)
            .asBottomList(
                "", arrayOf(
                    "标准地图",
                    "卫星地图"
                )
            ) { i, _ ->
                when (i) {
                    0 -> {
                        aMap.mapType = AMap.MAP_TYPE_NORMAL
                    }
                    else -> {
                        aMap.mapType = AMap.MAP_TYPE_SATELLITE
                    }
                }
            }.show()
    }

    /**
     * 根据类型 转换 坐标
     */
    fun convert(sourceLatLng: LatLng?): LatLng? {
        val converter = CoordinateConverter(context)
        // CoordType.GPS 待转换坐标类型
        converter.from(CoordinateConverter.CoordType.GPS)
        // sourceLatLng待转换坐标点
        converter.coord(sourceLatLng)
        // 执行转换操作
        return converter.convert()
    }

    fun getMapObj(PipeFileBeanDOBeanList: List<PipeFileBeanDO>) {
        removeMypolyline()
        PipeFileBeanDOBeanList.forEachIndexed { index, pipeFileBeanDO ->
            // 绘制点列表
            val pointList2: MutableList<DrawLatLng> = mutableListOf()
            pipeFileBeanDO.fileNodesBeanDO?.forEach {
                val latLng = LatLng(it.latitude, it.longitude.toDouble())
                var drawLatLng = DrawLatLng(convert(latLng)!!, false)
                pointList2.add(drawLatLng)
                if (pointList2.size > 0) {
                    val addPolyline =
                        this.aMap.addPolyline(PolylineOptions().addAll(DrawMapUtils.drawLatLngToLatLng(
                            pointList2)).width(2f).color(Color.parseColor("#FF0000"))
                            .zIndex(999f))  // 线颜色
                    myPolylineList.add(addPolyline)
                    if (index == 0) {
                        aMap.moveCamera(CameraUpdateFactory.newCameraPosition(CameraPosition(
                            pointList2[0].latLng,
                            14f,
                            0f,
                            0f)))
                    }
                }
            }
        }

    }

    // 绘制线
    private val myPolylineList: MutableList<Polyline> = mutableListOf()

    fun removeMypolyline() {
        myPolylineList.forEach {
            it.remove()
        }
    }

    // 行政区域
    private var districtPoints: MutableList<Polyline> = mutableListOf()

    /**
     * 搜索行政区
     */
    private fun searchDistrict(index :Int,searchName: String, provincesName: String? = null, address: String? = null) {
        val search = DistrictSearch(requireContext())
        val query = DistrictSearchQuery(provincesName, DistrictSearchQuery.KEYWORDS_CITY, 0)
        // 是否返回边界值
        query.isShowBoundary = true
        //不显示子区域边界
        query.isShowChild = false
        query.keywords = searchName
        search.query = query
        search.setOnDistrictSearchListener { districtResult ->
            if (districtResult?.district != null) {
                if (districtResult.aMapException.errorCode == AMapException.CODE_AMAP_SUCCESS) {
                    Logs.d("polygonDraw: " + districtResult.pageCount)
                    Logs.d("polygonDraw: " + districtResult.district.size)
                    polygonDraw(index,districtResult.district, address)
                }
            }
        }
        // 开始搜索
        search.searchDistrictAsyn()
    }

    private fun polygonDraw(position :Int,data: List<DistrictItem>, address: String? = null) {
        ThreadUtils.executeBySingle(object : ThreadUtils.Task<ArrayList<LatLng>?>() {
            override fun doInBackground(): ArrayList<LatLng>? {
                val points: ArrayList<LatLng> = ArrayList()
                if (data.isNotEmpty()) {
                    val boundary = data[0].districtBoundary()
                    if (boundary.isNotEmpty()) {
                        val center = data[0].center
                        var index = 0
                        var count = 0
                        for (i in boundary.indices) {
                            if (boundary[i].length >= count) {
                                count = boundary[i].length
                                index = i
                            }
                        }
                        val str = boundary[index]
                        val latLngList = str.split(";".toRegex()).toTypedArray()
                        for (element in latLngList) {
                            val latLngStr: List<String> = element.split(",")
                            if (latLngStr.size == 2) {
                                try {
                                    val lng = latLngStr[0].toDouble()
                                    val lat = latLngStr[1].toDouble()
                                    points.add(LatLng(lat, lng))
                                } catch (e: Exception) {
                                    Logs.e("onDistrictSearched: cast error")
                                }
                            }
                        }
                        if (position==0) {
                            //移动到marker位置
                            val mCameraUpdate: CameraUpdate = CameraUpdateFactory.newCameraPosition(
                                CameraPosition(
                                    LatLng(center.latitude, center.longitude),
                                    8f,
                                    0f,
                                    0f
                                )
                            )
                            aMap.moveCamera(mCameraUpdate)
                        }
                    }
                    return points
                }
                return null
            }

            override fun onSuccess(result: ArrayList<LatLng>?) {
//                districtPoints = result
                //显示行政区域范围

                val addPolyline = aMap.addPolyline(PolylineOptions().addAll(result).width(10f).color(Color.BLUE).setDottedLine(false))
                districtPoints.add(addPolyline)
            }

            override fun onCancel() {

            }

            override fun onFail(t: Throwable?) {

            }

        })
    }


    fun removeDistrictMap(){
        districtPoints.forEach {
            it.remove()
        }
    }

}